using System;
using System.Web.UI;
using Microsoft.Web.Mvc.Controls;

namespace MvcImproved.Generic.Controls
{
	// This is a generic control that can be used directly on
	// an ASPX page with some special syntax.
	public abstract class GenericControl<TDataItem, TMemberValue> : MvcControl
	{
		protected Func<TDataItem, TMemberValue> ValueMemberLambda;
		public TDataItem DataValue;

		public string DataKey
		{
			get;
			set;
		}

		public string ValueMember
		{
			get;
			set;
		}

		protected virtual void InitViewData()
		{
			if ((DesignMode) || (DataValue != null))
				return;

			try
			{
				if (DataKey == null)
					DataValue = (TDataItem)ViewData.Model;
				else
				{
					object modelValue;
					if (ViewData.TryGetValue(DataKey, out modelValue))
						DataValue = (TDataItem)modelValue;
				}
			}
			catch (Exception)
			{
				if (DataKey == null)
					throw new InvalidOperationException("No model specified, and default model is not of type " + typeof(TDataItem).ToString());
				else
					throw new InvalidOperationException(String.Format("ViewData[{0}] is not of type {1}", DataKey, typeof(TDataItem).ToString()));
			}
		}

		protected override void OnPreRender(EventArgs e)
		{
			base.OnPreRender(e);

			InitViewData();
		}

		protected override void Render(HtmlTextWriter writer)
		{
			InitViewData();

			base.Render(writer);

			if (DesignMode)
			{
				string designDisplay = DataKey;
				if (DataKey == null)
					designDisplay = ValueMember;
				else if (ValueMember != null)
					designDisplay = String.Format("{0}.{1}", DataKey, ValueMember);
				writer.Write(designDisplay);
			}
		}

		protected GenericControl(Func<TDataItem, TMemberValue> valueMember)
		{
			ValueMemberLambda = valueMember;
		}
	}
}
